/*
 *  Copyright 2012 yura.
 * 
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 * 
 *       http://www.apache.org/licenses/LICENSE-2.0
 * 
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 *  under the License.
 */

package org.opu.odg.dg.logicbeans;

import org.opu.odg.dg.logicbeans.ArchiveFileTemplateForDG.*;
import org.simpleframework.xml.ElementUnion;
import java.io.Serializable;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import org.opu.odg.dg.incomingdata.ContentDescription;
import org.opu.odg.dg.incomingdata.CustomContentDescription;
import org.opu.odg.dg.incomingdata.DatabaseContentDescription;
import org.simpleframework.xml.Attribute;
import org.simpleframework.xml.Element;
import org.simpleframework.xml.ElementMap;
import org.simpleframework.xml.ElementMapUnion;
import org.simpleframework.xml.Root;

/**
 *
 * @author yura
 */
@Root(name=TemplateMetaInf.METAINF)
public class TemplateMetaInf implements Serializable {

    public static final String METAINF = "MetaInf";
    public static final String METAINF_XML = METAINF + ".xml";
    public static final String TEMPLATE_XML = "Template.___";

    public static enum Type {SingleFile, ArchiveFile}

    public static TemplateMetaInf getDocxBillet() {
        return new TemplateMetaInf(Type.ArchiveFile, new XpathEntryDeterminator(
                "[Content_Types].xml", Arrays.asList(
                "//*[@ContentType='application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml']/@PartName",
                "//*[@ContentType='application/vnd.openxmlformats-officedocument.wordprocessingml.header+xml']/@PartName",
                "//*[@ContentType='application/vnd.openxmlformats-officedocument.wordprocessingml.footer+xml']/@PartName")),
                new HashMap<String, ContentDescription>());
    }

    public static TemplateMetaInf getOdtBillet() {
        return new TemplateMetaInf(Type.ArchiveFile,
                new DirectFileNamesEntryDeterminator(Arrays.asList("/content.xml")),
                new HashMap<String, ContentDescription>());
    }

    public static TemplateMetaInf getXmlBillet() {
        return new TemplateMetaInf(Type.SingleFile,
                null,
                new HashMap<String, ContentDescription>());
    }


    @Attribute
    private Type type;

    @ElementUnion({
        @Element(required=false,name="FileNames",type=DirectFileNamesEntryDeterminator.class),
        @Element(required=false,name="XpathEntry",type=XpathEntryDeterminator.class)
    })
    private ChangeableEntryDeterminator entryDeterminator;

    @Element(required=false, name="contents")
    private ContentHolder contentHolder = new ContentHolder();

    private TemplateMetaInf() {
    }

    public TemplateMetaInf(Type type, ChangeableEntryDeterminator entryDeterminator,
            Map<String, ContentDescription> contents) {
        this.type = type;
        this.entryDeterminator = entryDeterminator;
        this.contentHolder.setContents(contents);
    }

    public ChangeableEntryDeterminator getEntryDeterminator() {
        return entryDeterminator;
    }

    public void setEntryDeterminator(ChangeableEntryDeterminator entryDeterminator) {
        this.entryDeterminator = entryDeterminator;
    }

    public Type getType() {
        return type;
    }

    public void setType(Type type) {
        this.type = type;
    }

    public Map<String, ContentDescription> getContents() {
        return contentHolder.contents;
    }

    public void setContents(Map<String, ContentDescription> contents) {
        this.contentHolder.setContents(contents);
    }

    @Override
    public boolean equals(Object obj) {
        if (obj == null) {
            return false;
        }
        if (getClass() != obj.getClass()) {
            return false;
        }
        final TemplateMetaInf other = (TemplateMetaInf) obj;
        if (this.type != other.type) {
            return false;
        }
        if (this.entryDeterminator != other.entryDeterminator && (this.entryDeterminator == null || !this.entryDeterminator.equals(other.entryDeterminator))) {
            return false;
        }
        return true;
    }

    @Override
    public int hashCode() {
        int hash = 7;
        hash = 97 * hash + (this.type != null ? this.type.hashCode() : 0);
        hash = 97 * hash + (this.entryDeterminator != null ? this.entryDeterminator.hashCode() : 0);
        return hash;
    }

    public static class ContentHolder {
        @ElementMapUnion({
            @ElementMap(keyType=String.class, key="custom", inline=true, entry="custom",
                    valueType=CustomContentDescription.class, attribute=true, required=false),
            @ElementMap(keyType=String.class, key="database", inline=true, entry="database",
                    valueType=DatabaseContentDescription.class, attribute=true, required=false)
        })
        private HashMap<String, ContentDescription> contents = new HashMap<String, ContentDescription>();

        public Map<String, ContentDescription> getContents() {
            return contents;
        }

        public void setContents(Map<String, ContentDescription> contents) {
            this.contents = new HashMap<String, ContentDescription>();
            if (contents != null) {
                this.contents.putAll(contents);
            }
        }
    }
}
